package dbpool;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.LinkedList;
import java.util.Properties;

/**
 * 自定义连接池
 * @author ALIENWARE
 *
 */
public class DbPool {
	//单例对象
	private static DbPool pool;
	
	private static String driverClass;
	private static String url;
	private static String userName;
	private static String password; //连接属性
	
	private static int initCount = 3;//初始连接
	private static int minCount = 3;//最小连接数
	private static int maxCount = 10;//最大连接数
	private static int count;//当前的连接数
	
	//用集合存池子
	LinkedList<Connection> conns = new LinkedList<Connection>();
	
	static {
		Properties properties = new Properties();
		InputStream file = DbPool.class.getClassLoader().getResourceAsStream("db.properties");
		try {
			properties.load(file);
			driverClass = properties.getProperty("jdbc.driverClass");
			url = properties.getProperty("jdbc.url");
			userName = properties.getProperty("jdbc.userName");
			password = properties.getProperty("jdbc.password");
			//用户不配置，使用默认值
			try {
				initCount = new Integer(properties.getProperty("jdbc.initCount"));
	
			}catch (Exception e) {
			
			}
			try {
				minCount = new Integer(properties.getProperty("jdbc.minCount"));
				
			}catch (Exception e) {
				
			}
			try {
				maxCount =  new Integer(properties.getProperty("jdbc.maxCount"));
			}catch (Exception e) {
				
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public synchronized static DbPool getPool() {
		if(pool == null) {
			pool = new DbPool();
		}
		return pool;
	}
	
	//构造方法私有化
	private DbPool() {
		init();
	}
	
	//初始化连接池
	private void init() {
		//循环集合里添加
		for (int i = 0; i < initCount; i++) {
			boolean ok = conns.add(createConn());
			if(ok) {
				count++;
			}
			
		}
		System.out.println("连接池初始化完成，连接数量="+count);
	}
	//获取连接的方法
	private Connection createConn() {
		try {
			Class.forName(driverClass);
			return DriverManager.getConnection(url,userName,password);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException("连接创建失败"+e.getMessage());
		}
	}
	
	//增加链接的方法
	private synchronized void autoAdd() {
		//步长为2
		if(count == maxCount) {
			throw new RuntimeException("连接池满了，不能再增加");
		}
		for (int i = 0; i < 2; i++) {
			conns.add(createConn());
			count++;
			if(count == maxCount) {
				break;
			}
		}
	}
	
	//获取连接池的连接
	public Connection getConn() {
		//判断池子里有没有连接
		if(conns.size() > 0) {
			return conns.removeFirst();
		}
		//如果没有了，总连接数没到上限
		if(count < maxCount) {
			autoAdd();
			//增加完后，递归调用自己
			return getConn();
		}
		//总连接数已到上限,就等待一会再去获取
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		
		return getConn();
	}
	
	
	//连接池自动缩进
	public synchronized void sub() {
		//空闲的连接大于最小连接数
		if(conns.size() > 0) {
			try {
				Connection conn = conns.removeFirst();
				conn.close();
				conn = null;
				//连接数-1
				count--;
			}catch (Exception e) {
				e.printStackTrace();
			}
			
		}
	}
	//还回连接
	public void back(Connection conn) {
		conns.add(conn);//加入集合
		//是否要缩减，优化
		sub();
	}
	
}
